package org.windowkit.toolkit.widget.table.render;

import java.awt.Component;

import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;

import org.ddevil.data.Data;
import org.windowkit.toolkit.widget.table.RecordTableModel;

/**
 * Base class for renders that decorate another renderer.
 * Typical behavior is call off to the main renderer to do the normal rendering
 * and then decorate the returned component here based on the data being rendered.
 * e.g. set bg color based on the data.
 *
 * @author Rich
 */
public abstract class AbstractTableCellRendererDecorator implements TableCellRenderer {
	private final TableCellRenderer renderer;

	/**
	 * Value object holding info about the cell being rendered.
	 */
	public static class CellInfo {
		public boolean isSelected;
		public boolean hasFocus;
		public int row;
		public int column;
		public CellInfo(final boolean isSelected, final boolean hasFocus, final int row, final int column) {
			this.isSelected = isSelected;
			this.hasFocus = hasFocus;
			this.row = row;
			this.column = column;
		}
		public boolean isSelected() {
			return isSelected;
		}
		public boolean isHasFocus() {
			return hasFocus;
		}
		public int getRow() {
			return row;
		}
		public int getColumn() {
			return column;
		}
	}

	/**
	 * Constructor.
	 */
	public AbstractTableCellRendererDecorator() {
		renderer = createRenderer();
	}

	/**
	 * Constructor.
	 * @param decorateMe the renderer that will be decorated. This renderer is called first to create
	 * the initial cell component.
	 */
	public AbstractTableCellRendererDecorator(final TableCellRenderer decorateMe) {
		renderer = decorateMe;
	}

	/**
	 * Create the renderer that is being decorated.
	 * @return table cell renderer
	 */
	protected TableCellRenderer createRenderer() {
		return new DefaultTableCellRenderer();
	}

	/**
	 * {@inheritDoc}
	 */
	public Component getTableCellRendererComponent(final JTable table, final Object value,
			final boolean isSelected, final boolean hasFocus, final int row, final int column) {

		Component c = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);


		RecordTableModel model = (RecordTableModel)table.getModel();
		Data d = model.getRecord(row);

		decorate(c, d, model, table, value, new CellInfo(isSelected, hasFocus, row, column));

		return c;
	}

	/**
	 * Extension point to do decoration.
	 * @param c component that represents the cell being rendered
	 * @param d data for current row
	 * @param model table model
	 * @param table the table component
	 * @param value the value being rendered
	 * @param cellInfo composite of all the cell information
	 */
	protected abstract void decorate(Component c,
			Data d, RecordTableModel model, JTable table, Object value,
			CellInfo cellInfo);
}
